package com.zjy.business.system.manager.service.impl;

import com.github.pagehelper.PageInfo;
import com.zjy.business.system.common.SysPermissionCommon;
import com.zjy.business.system.dao.SysRoleDao;
import com.zjy.business.system.dao.SysRoleMenuDao;
import com.zjy.business.system.dao.SysUserRoleDao;
import com.zjy.business.system.domain.entity.SysRole;
import com.zjy.business.system.domain.entity.SysRoleMenu;
import com.zjy.business.system.domain.manager.form.ManagerSysRoleSaveOrUpdateForm;
import com.zjy.business.system.domain.manager.query.ManagerListPageSysRoleQuery;
import com.zjy.business.system.domain.manager.vo.ManagerListPageSysRoleVo;
import com.zjy.business.system.manager.service.ManagerSysRoleService;
import com.zjy.common.constant.StringConstant;
import com.zjy.common.utils.ConvertBeanUtils;
import com.zjy.web.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * @author yxb
 * create_time: 2024-10-22 16:14
 * description: 
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ManagerSysRoleServiceImpl implements ManagerSysRoleService {

    final private SysRoleDao sysRoleDao;

    final private SysRoleMenuDao sysRoleMenuDao;

    final private SysPermissionCommon sysPermissionCommon;

    final private SysUserRoleDao sysUserRoleDao;


    @Override
    @Transactional
    public void saveOrUpdateRole(ManagerSysRoleSaveOrUpdateForm form) {
        checkSaveOrUpdateForm(form);
        Long id = form.getId();
        if (Objects.isNull(id)) {
            SysRole role = ConvertBeanUtils.convert(form, SysRole.class);
            sysRoleDao.save(role);
            // 保存角色权限
            saveOrUpdateRolePermission(role.getId(), form.getMenuIdList(), false);
        } else {
            SysRole sysRole = sysRoleDao.getById(id);
            if (Objects.isNull(sysRole)) {
                throw BusinessException.EXCEPTION("角色不存在");
            }
            sysRole.setName(form.getName());
            sysRole.setRoleKey(form.getRoleKey());
            sysRole.setStatus(form.getStatus());
            sysRole.setSortValue(form.getSortValue());
            sysRole.setRemark(form.getRemark());
            sysRoleDao.updateByIdUpdateCache(sysRole, SysRole::getId, id);
            // 保存角色权限
            saveOrUpdateRolePermission(form.getId(), form.getMenuIdList(), true);
            sysPermissionCommon.clearByRoleId(sysRole.getId());
            sysRoleMenuDao.delCache(SysRoleMenu::getRoleId, sysRole.getId());
        }
    }

    /**
     * 保存或更新角色权限信息
     * @param roleId 角色id
     * @param menuIdList 菜单集合
     * @param clear 是否清空角色权限信息
     */
    public void saveOrUpdateRolePermission(Long roleId, List<Long> menuIdList, boolean clear) {
        if (clear) {
            sysRoleMenuDao.removeByRoleId(roleId);
        }
        if (ObjectUtils.isNotEmpty(menuIdList)) {
            // 添加角色绑定权限信息
            sysRoleMenuDao.saveBatch(menuIdList.stream().map(item -> {
                SysRoleMenu sysRoleMenu = new SysRoleMenu();
                sysRoleMenu.setRoleId(roleId);
                sysRoleMenu.setMenuId(item);
                return sysRoleMenu;
            }).toList());
        }
    }


    private void checkSaveOrUpdateForm(ManagerSysRoleSaveOrUpdateForm form) {
        sysRoleDao.lambdaQuery()
                .eq(SysRole::getRoleKey, form.getRoleKey())
                .ne(Objects.nonNull(form.getId()), SysRole::getRoleKey, form.getRoleKey())
                .oneOpt()
                .ifPresent(item -> {
                    throw BusinessException.EXCEPTION("已存在相同角色标识");
                });
        sysRoleDao.lambdaQuery()
                .eq(SysRole::getName, form.getName())
                .ne(Objects.nonNull(form.getId()), SysRole::getId, form.getId())
                .oneOpt()
                .ifPresent(user -> {
                    throw BusinessException.EXCEPTION("已存在相同角色名称");
                });
    }

    @Override
    @Transactional
    public void remove(Long id) {
        SysRole sysRole = sysRoleDao.findCacheOne(SysRole::getId, id);
        if (Objects.isNull(sysRole)) {
            throw BusinessException.EXCEPTION("角色不存在");
        }
        // 判断角色是否为超级管理员角色
        if (StringUtils.equals(sysRole.getRoleKey(), StringConstant.ROLE_SUPER_ADMIN)) {
            throw BusinessException.EXCEPTION("超级管理员角色不能删除");
        }
        long count = sysUserRoleDao.checkRoleIsBindUser(id);
        if (count > 0) {
            throw BusinessException.EXCEPTION("角色已绑定用户,不能删除");
        }
        // 清理角色绑定菜单信息
        sysRoleMenuDao.removeByRoleId(id);
        // 清除角色数据
        sysRoleDao.removeByIdDeleteCache(id, SysRole::getId, id);
    }

    @Override
    public PageInfo<ManagerListPageSysRoleVo> listPageSysRole(ManagerListPageSysRoleQuery query) {
        List<ManagerListPageSysRoleVo> result = sysRoleDao.listPageSysRole(query);
        return PageInfo.of(result);
    }

    @Override
    public List<SysRole> roleDownList() {
        return sysRoleDao.lambdaQuery()
                .select(SysRole::getId, SysRole::getName)
                .orderByDesc(SysRole::getId)
                .list();
    }

}
